home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PD Collection CD 1
/
PD Collection CD 1.iso
/
textual
/
pdimpres
/
!PD-Impres
/
c
/
PD-Impres
< prev
Wrap
Text File
|
1990-08-25
|
18KB
|
450 lines
/* -> c.PD-Impres */
/*
* Desktop utility to convert PipeDream documents into text files suitable for Impression, while still retaining style and
* formatting information where possible. The utility lives on the icon bar, converting any PipeDream (type DDE) dropped there).
* ie This program converts PipeDream documents into DDF format text
*
* © Stuart Hickinbottom 31mar90
*/
/* #define TRACE TRUE */ /* Comment out this macro definition to produce a production version of the code */
/* Include the various headers I require... */
#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "event.h"
#include "baricon.h"
#include "res.h"
#include "resspr.h"
#include "menu.h"
#include "template.h"
#include "dbox.h"
#include "werr.h"
#include "xferrecv.h"
#include "trace.h"
#include "visdelay.h"
#include "saveas.h"
#include "flex.h"
#include "bbc.h"
#include <string.h>
#include <stdlib.h>
/* Define any constants which I require... */
#define PDImpress_menu_info 1 /* Menu items */
#define PDImpress_menu_quit 2
#define PDImpress_info_field 4 /* Info box icon number for the version string */
#define PDImpress_loadtype 0xdde
#define PDImpress_savetype 0xfff
#define Special_character '%' /* The special character that indicates a command */
#define Max_highlight_size 50 /* The maximum length of a PipeDream highlight code, I think this is column definition */
#define Buffer_increase 512 /* Define the amount by which the buffer is incremented. Should be >= max DDF line length */
#define RAM_xfername "DDF_File" /* Define the name to be used in the export box if RAM xfer used */
/* Define any constant static data which I need... */
static char *pdimpress_Version_String = "0.13 (31 March 1990)"; /* Application version text */
static menu pdimpress_menu; /* The top of the menu tree */
static char in_file_name[255]; /* Hold the file name of the PipeDream file */
static char *in_file = in_file_name; /* Point to this memory */
static char *pd_text = NULL; /* Pointer to loaded PipeDream text in memory */
static char *ddf_text = NULL; /* Pointer to DDF format converted text */
static int ddf_size; /* The size of the DDF text buffer. Increases */
static int pd_file_size; /* The size of the PipeDream document */
static int offset_ddf; /* The offset into the DDF text buffer */
static int offset_pd; /* The offset into the PD text buffer */
/*
* This table defines the translation from PipeDream highlight codes to Impression DDF commands. For each highlight code
* there is the PipeDream command name and then the Impression style name. There is then a flag which this code uses to
* remember whether the style is currently on or off. This table may be freely expanded.
*/
static char *highlight_trans[][] =
{
{"H1", "Underline", "Off"}, /* Style: Underline */
{"H2", "Bold", "Off"}, /* Style: Bold */
{"H3", "Main Heading", "Off"}, /* Style: Extended sequence */
{"H4", "Italic", "Off"}, /* Style: Italic */
{"H5", "Subscript", "Off"}, /* Style: Subscript */
{"H6", "Superscript", "Off"}, /* Style: Superscript */
{"H7", "Typewriter", "Off"}, /* Style: Alternative font */
{"H8", "Sub-heading", "Off"}, /* Style: User defined */
{"JL", "Fully Justify", "Off"}, /* Style: Justified */
{"JR", "Fully Justify", "Off"}, /* Style: Justified */
{"C", "Centre", "Off"}, /* Justify: Centre */
{"**", "", "" } /* Terminating value */
};
static char *highlight_ignore[] = /* Define highlight codes which cause the 'interpreter' to skip the line */
{
"OP", /* Ignore page description lines */
"**", /* Terminating value */
};
/* Table of special highlights which are converted directly into text, for example the percentage symbol */
static char *highlight_text[][] =
{
{"PC", "%" }, /* Convert PC into the percentage symbol */
{"**", "" } /* Terminating value */
};
/* Any highlight code which is not in any of the above tables is simply skipped over - no action is taken */
/* Main program polling loop */
int main()
{
BOOL pdimpress_initialise(void);
if (pdimpress_initialise())
{
while (TRUE) /* The main event loop */
event_process();
}
return 0; /* Return, as there was a problem which prevented successful initialisation */
}
/* Event handler called on a left click on the icon */
void pdimpress_iconclick(wimp_i icon)
{
void pdimpress_info_about_program(void);
icon = icon; /* We don't need the handle: this stops compiler warning */
pdimpress_info_about_program(); /* Just display 'About this program' window */
}
/* Display the program info box - called from the menu processor */
void pdimpress_info_about_program(void)
{
dbox d; /* Dialogue box handle */
if (d = dbox_new("progInfo"), d != NULL) /* Create the dialogue box */
{
dbox_setfield(d, PDImpress_info_field, pdimpress_Version_String); /* Fill in the version number */
dbox_show(d); /* Show the dialogue box */
dbox_fillin(d); /* Keep it on the screen as long as needed */
dbox_dispose(&d); /* Dispose of the dialogue box */
}
}
/* Event handler for the menu */
void pdimpress_menuproc(void *handle, char *hit)
{
handle = handle; /* We don't need handle: this stops compiler warning */
switch (hit[0]) /* Find which menu item was hit and take action as appropriate */
{
case PDImpress_menu_info:
pdimpress_info_about_program();
break;
case PDImpress_menu_quit:
exit(0); /* Exit from the program. The wimp gets rid of the window and icon */
}
}
/* Event handler for icon bar events */
BOOL pdimpress_bar_event_handler(wimp_eventstr *e, void *handle)
{
void load_ram(void), load_file(void);
handle = handle; /* We don't need handle: this stops compiler warning */
switch (e->e) /* Deal with event */
{
case wimp_ESEND:
case wimp_ESENDWANTACK:
switch (e->data.msg.hdr.action)
{
case wimp_MDATASAVE:
load_ram();
return(TRUE);
case wimp_MDATALOAD:
case wimp_MDATAOPEN:
load_file();
return(TRUE);
}
default: /* Ignore any other event */
return(FALSE);
}
}
/* Load the file, utilising direct RAM data transfer from another application */
void load_ram(void)
{
BOOL buffer_processor(char **, int *);
void load_file(void), convert_pd_file(int), do_ddf_save(void), clean_up(void);
int estimated_size, actual_size, file_type, alloc_success;
file_type = xferrecv_checkimport(&estimated_size);
if (file_type != -1) /* If we really can load via RAM then... */
{
if (file_type == PDImpress_loadtype)
{
pd_file_size = 0;
if ((alloc_success = flex_alloc((flex_ptr) &pd_text, estimated_size)) == NULL)
werr(FALSE,"There is not enough memory to load the PipeDream document - try to free some using the Task Manager");
else
{
visdelay_begin();
in_file = RAM_xfername; /* Make up a name, as there isn't one supplied on RAM xfer */
tracef1("estimated RAM xfer size is %d bytes\n", estimated_size);
actual_size = xferrecv_doimport(pd_text, estimated_size, buffer_processor);
tracef1("xfer was %d bytes\n", pd_file_size);
if (actual_size >= 0) /* If the xfer was successful then... */
{
convert_pd_file(pd_file_size);
visdelay_end();
if (ddf_size != 0) do_ddf_save();
clean_up();
}
else /* There was an error during the xfer */
{
flex_free((flex_ptr) &pd_text);
visdelay_end();
/* Sender got scared during the RAM xfer? The sending application should try by file instead... */
}
}
}
}
else
{
load_file();
}
}
/* Handle the RAM buffer becomming full during the RAM xfer */
BOOL buffer_processor(char **buffer, int *size)
{
int success_flag;
pd_file_size += *size; /* Record number of bytes xfer'd so far */
tracef0("buffer processor called\n");
success_flag = flex_extend((flex_ptr) &pd_text, pd_file_size + Buffer_increase);
if (success_flag == 0)
{
tracef0("Not enough memory during buffer_processor\n");
return(FALSE); /* If buffer increase failed, then return error */
}
*buffer += *size; /* Advance the buffer pointer into the new area */
*size = Buffer_increase; /* Size to xfer is this new areas size */
return TRUE; /* Continue the xfer */
}
/* Handle a file icon being dropped onto me. If it is acceptable then load it */
void load_file(void)
{
char *filename;
void convert_pd_file(int), do_ddf_save(void), clean_up(void);
int read_pd_file(void);
int filetype = xferrecv_checkinsert(&filename);
strcpy(in_file, filename);
tracef1("load_file, filetype %x\n", filetype);
if (filetype == PDImpress_loadtype)
{
visdelay_begin();
tracef0("loading file....\n");
pd_file_size = read_pd_file();
if (pd_file_size != 0) convert_pd_file(pd_file_size);
xferrecv_insertfileok();
visdelay_end();
if ((pd_file_size != 0) && (ddf_size != 0)) do_ddf_save(); /* Do save if dragged to something that wants the DDF text file */
clean_up(); /* Dispose of PipeDream and DDF documents from the flex area */
}
}
/* Initialise the program, returning TRUE if it was all OK */
BOOL pdimpress_initialise(void)
{
/* RISC_OSlib initialisation of the various modules I use */
wimpt_init("PD -> Impression"); /* Main Wimp initialisation */
res_init("PD-Impres"); /* Resources */
resspr_init(); /* Application sprites */
template_init(); /* Templates */
dbox_init(); /* Dialogue boxes */
visdelay_init(); /* Hourglass */
flex_init(); /* Flex */
if (pdimpress_menu = menu_new("PD-Impres", ">Info,Quit"), pdimpress_menu == NULL) /* Create the menu tree */
return FALSE; /* Menu create failed */
win_add_unknown_event_processor(pdimpress_bar_event_handler, 0); /* Grab unknown events for my icon (files dropped etc.) */
baricon("!PD-Impres", (int)resspr_area(), pdimpress_iconclick); /* Set up the icon on the bar, and declare its event handlers */
if (!event_attachmenu(win_ICONBAR, pdimpress_menu, pdimpress_menuproc, 0))
return FALSE; /* Unable to attach menu */
trace_on(); /* Turn tracing on. This will only occur if the macro TRACE was defined at the start, though */
return TRUE; /* All went ok, so indicate this */
}
/* Read in the PipeDream file, allocating enough space to hold the entire file in one go */
int read_pd_file(void)
{
FILE *pd_file_handle;
int pd_file_size, alloc_success;
tracef0("opening file");
if ((pd_file_handle = fopen(in_file, "r")) == NULL)
{
werr(FALSE, "Strange, the PipeDream file could not be opened (not found?)");
return(0); /* Return a length of 0 - not loaded */
}
fseek(pd_file_handle, 0,2);
pd_file_size = (int)ftell(pd_file_handle);
fseek(pd_file_handle, 0,0);
tracef1(", file size is %d bytes\n", pd_file_size);
if ((alloc_success = flex_alloc((flex_ptr) &pd_text, pd_file_size)) == NULL)
{
werr(FALSE,"There is not enough memory to load the PipeDream document - try to free some using the Task Manager");
fclose(pd_file_handle);
return(0);
}
tracef0("reading text from file\n");
fread(pd_text, 1, pd_file_size, pd_file_handle);
tracef0("closing file\n");
fclose(pd_file_handle);
return(pd_file_size);
}
/* Write out the DDF format version of the text to a file */
BOOL write_ddf_file(char *out_file, void *handle)
{
os_filestr file;
BOOL ok;
handle = handle; /* Stop compiler warning */
file.action = 0x0a; /* Save block and date stamp file */
file.name = out_file;
file.loadaddr = PDImpress_savetype; /* File type */
file.start = (int)ddf_text;
file.end = (int)(ddf_text + offset_ddf);
ok = (wimpt_complain(os_file(&file)) == 0);
tracef1("written %d bytes\n", (int)offset_ddf);
return(ok);
}
/* Clean up at the end of the conversion, or if an error has occured - ie free memory etc. */
void clean_up(void)
{
if (pd_text != 0) flex_free((flex_ptr) &pd_text);
if (ddf_text != 0) flex_free((flex_ptr) &ddf_text);
}
/* Convert the PipeDream file into a DDF format file - this is the biggie!! */
void convert_pd_file(int pd_file_size)
{
void handle_embedded(void), all_highlights_off(void), ensure_highlights_off(void), increase_buffer(void);
int success_flag;
tracef1("converting text (%d bytes source), ", pd_file_size);
offset_pd = 0;
offset_ddf = 0;
ddf_size = Buffer_increase;
success_flag = flex_alloc((flex_ptr) &ddf_text, Buffer_increase);
if (success_flag == 0)
{
werr(FALSE, "There is not enough memory to convert the PipeDream document - try to free some using the Task Manager");
flex_free((flex_ptr) &ddf_text);
ddf_size = 0;
}
all_highlights_off();
while ((offset_pd < pd_file_size) && (ddf_size != 0))
{
while (pd_text[offset_pd] == Special_character) handle_embedded();
if ((pd_text[offset_pd] == '\x0a') || (pd_text[offset_pd] == '\x0d')) ensure_highlights_off();
if (offset_pd < pd_file_size) ddf_text[offset_ddf++] = pd_text[offset_pd];
offset_pd++;
if ((ddf_size - offset_ddf) < Buffer_increase)
increase_buffer();
}
tracef0("done\n");
}
/* Handle an embedded command, converting it into DDF */
void handle_embedded(void)
{
char character, *highlight;
int highlight_size, highlight_number, strcmp(char *, char *);
void toggle_highlight_on(int), insert_ddf(int);
flex_alloc((flex_ptr) &highlight, Max_highlight_size);
highlight_size = 0;
while ((character = pd_text[++offset_pd]) != Special_character) highlight[highlight_size++] = character; /* Read command */
offset_pd++;
highlight[highlight_size] = NULL;
highlight_number = 0;
while ((strcmp(highlight_ignore[highlight_number], "**") != 0) && strcmp(highlight_ignore[highlight_number], highlight) != 0)
highlight_number++; /* Check if this command is to be ignored */
if (strcmp(highlight_ignore[highlight_number], "**") != 0) /* If this command should be ignored then... */
while ((pd_text[offset_pd] != '\x0a') && (pd_text[offset_pd++] != '\x0d')); /* Skip the rest of this line */
else
{
highlight_number = 0;
while ((strcmp(highlight_trans[highlight_number][0], "**") != 0) && strcmp(highlight_trans[highlight_number][0], highlight) != 0)
highlight_number++; /* Check if this command is to be translated to a DDF command */
if (strcmp(highlight_trans[highlight_number][0], "**") != 0) /* If this command should be translated then... */
{
toggle_highlight_on(highlight_number);
insert_ddf(highlight_number);
}
else
{
highlight_number = 0;
while ((strcmp(highlight_text[highlight_number][0], "**") != 0) && strcmp(highlight_text[highlight_number][0], highlight) != 0)
highlight_number++; /* Check if this command is to be translated to a text alternative */
if (strcmp(highlight_text[highlight_number][0], "**") != 0) /* If this command should be translated then... */
offset_ddf += sprintf(&(ddf_text[offset_ddf]), "%s", highlight_text[highlight_number][1]); /* Copy in the translated string */
}
}
flex_free((flex_ptr) &highlight);
}
/* Increase the buffer for the DDF text by the amount defined by Buffer_increase */
void increase_buffer(void)
{
int success_flag;
success_flag = flex_extend((flex_ptr) &ddf_text, ddf_size + Buffer_increase);
if (success_flag == 0)
{
werr(FALSE, "Insufficent memory to convert PipeDream document - try to free some using the Task Manager");
flex_free((flex_ptr) &ddf_text);
ddf_size = 0;
}
else
ddf_size += Buffer_increase;
}
/* Toggle my flag which indicates whether a highlight is currently turn on. Used to turn all off at end of a line */
void toggle_highlight_on(int highlight_number)
{
if (highlight_trans[highlight_number][2] == "Off")
highlight_trans[highlight_number][2] = "On";
else
highlight_trans[highlight_number][2] = "Off";
}
/* This inserts the DDF equivalent of the highlight code, using the 'on flag' to decide whether to turn it on or off */
void insert_ddf(int highlight_number)
{
offset_ddf += sprintf(&(ddf_text[offset_ddf]), "{\"%s\" %s}",
highlight_trans[highlight_number][1], highlight_trans[highlight_number][2]);
}
/* Reset all the highlights to be initially off */
void all_highlights_off(void)
{
int highlight_number, strcmp(char *, char *);
highlight_number = 0;
while (strcmp(highlight_trans[highlight_number][0], "**") != 0)
highlight_trans[highlight_number++][2] = "Off";
}
/* Ensure that all highlights are off at the end of a line, by issuing 'off' DDF commands to turn highlights off */
void ensure_highlights_off(void)
{
int highlight_number, strcmp(char*, char*);
void toggle_highlight_on(int), insert_ddf(int);
highlight_number = 0;
while (strcmp(highlight_trans[highlight_number][0], "**") != 0)
{
if (highlight_trans[highlight_number][2] == "On")
{
toggle_highlight_on(highlight_number);
insert_ddf(highlight_number);
}
highlight_number++;
}
}
/* Allow the user to export the DDF file, by dragging from the save dialogue box */
void do_ddf_save(void)
{
BOOL write_ddf_file(char *, void *);
saveas(PDImpress_savetype, in_file, offset_ddf, write_ddf_file, 0 /* No RAM xfer */, 0 /* No printer xfer */, 0);
}